package com.aim.config.shiro;

import com.aim.common.constant.Syscst;
import com.aim.common.enums.BizExceptionEnum;
import com.aim.common.enums.UserStatusEnum;
import com.aim.common.exception.ServiceException;
import com.aim.common.handler.FitContextHolder;
import com.aim.common.util.BeanUtils;
import com.aim.common.util.ConverterUtils;
import com.aim.common.util.OftenUtil;
import com.aim.entity.system.SysDept;
import com.aim.entity.system.SysRole;
import com.aim.entity.system.SysUser;
import org.apache.shiro.authc.CredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.DependsOn;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @AUTO 用户权限服务
 * @Author AIM
 * @DATE 2019/4/23
 */
@Service
@DependsOn("fitContextHolder")
@Transactional(readOnly = true)
public class UserAuthService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public static UserAuthService me() {
        return FitContextHolder.getBean(UserAuthService.class);
    }

    public ShiroUser user(String account) {
        StringBuffer sb = new StringBuffer("SELECT * FROM `sys_user` WHERE `ACCOUNT`=?");
        RowMapper<ShiroUser> rm = BeanPropertyRowMapper.newInstance(ShiroUser.class);
        try {
            ShiroUser user = this.jdbcTemplate.queryForObject(sb.toString(), new Object[]{account}, rm);
            // 账号被冻结
            if (!user.getStatus().equals(UserStatusEnum.OK.getCode())) {
                throw new LockedAccountException();
            }
            return user;
        } catch (EmptyResultDataAccessException e) {
            throw new CredentialsException();// 账号不存在
        }
    }

    public ShiroUser shiroUser(SysUser user) {
        ShiroUser shiroUser = new ShiroUser();
        BeanUtils.copyProperties(user, shiroUser);
        //用户角色数组
        List<String> roleArray = Arrays.asList(user.getRoleId().split(","));
        //获取用户角色列表
        List<Long> roleList = new ArrayList<Long>();
        Map<String, String> roles = new HashMap<String, String>();
        for (String str : roleArray) {
            Long roleId = ConverterUtils.toLong(str, -1);
            if (roleId != -1) {
                roleList.add(roleId);
                roles.put(roleId + "", getSingleRoleName(roleId));
            }
        }
        shiroUser.setRoleList(roleList);
        shiroUser.setRoles(roles);

        return shiroUser;
    }

    @Cacheable(value = Syscst.CONSTANT, key = "'" + Syscst.SINGLE_ROLE_NAME + "'+#roleId")
    public String getSingleRoleName(Long roleId) {
        if (0 == roleId) {
            return "--";
        }
        StringBuffer sb = new StringBuffer("SELECT * FROM `sys_role` WHERE `ROLE_ID`=?");
        RowMapper<SysRole> rm = BeanPropertyRowMapper.newInstance(SysRole.class);
        SysRole roleObj = this.jdbcTemplate.queryForObject(sb.toString(), new Object[]{roleId}, rm);
        if (OftenUtil.isNotEmpty(roleObj) && OftenUtil.isNotEmpty(roleObj.getName())) {
            return roleObj.getName();
        }
        return "";
    }

    /**
     * 判断当前登录的用户是否有操作这个用户的权限
     */
    public void assertAuth(Long userId) {
        if (ShiroKit.isAdmin()) {
            return;
        }
        StringBuffer sb = new StringBuffer("SELECT * FROM `sys_dept` WHERE `PIDS` LIKE ? ");
        List<SysDept> depts = this.jdbcTemplate.query(sb.toString(), new Object[]{"%[" + userId + "]%"}, new BeanPropertyRowMapper<SysDept>(SysDept.class));
        ArrayList<Long> deptDataScope = new ArrayList<>();
        if (depts != null && depts.size() > 0) {
            for (SysDept dept : depts) {
                deptDataScope.add(dept.getDeptId());
            }
        }
        sb.setLength(0);
        sb.append("SELECT * FROM `sys_user` WHERE `USER_ID`=?");
        RowMapper<ShiroUser> rm = BeanPropertyRowMapper.newInstance(ShiroUser.class);
        ShiroUser user = this.jdbcTemplate.queryForObject(sb.toString(), new Object[]{userId}, rm);
        Long deptId = user.getDeptId();
        if (deptDataScope.contains(deptId)) {
            return;
        } else {
            throw new ServiceException(BizExceptionEnum.NO_PERMITION);
        }
    }
}
